﻿/**
 *
 * load.c
 *
 *  Created on: 2019-12-03
 *      Author: chenshisheng
 */

#include "load.h"
#include "hw.h"
#include "master.h"
#include "active.h"
#include "utils.h"

#define _SERIAL Serial_4

// 上传的数据帧的帧头字节
#define FRAME_HEAD 0x55

#define FRAME_SIZE (2 + (sizeof(int32_t) * (1 + 4)) + 1)

#define FRAME_RAW_DATA_OFFSET (2 + sizeof(int32_t))

#define STATUS_NOT_CALIBRATED 0x01
#define STATUS_SENSOR_1_ERROR (0x01 << 1)
#define STATUS_SENSOR_2_ERROR (0x01 << 2)
#define STATUS_SENSOR_3_ERROR (0x01 << 3)
#define STATUS_SENSOR_4_ERROR (0x01 << 4)
#define STATUS_ERROR          (0x01 << 5)


void Load_Init(void)
{
//    HW_Config(HW_Out_LoadEn, HW_State_Inactive);
    Serial_IoCtl(_SERIAL, Serial_Ctl_RxCmd, DISABLE);
}

static inline uint8_t _CalcChecksum(const void *data, unsigned int size)
{
    return Utils_Crc8(data, size);
}

bool _FrameCheck(const void *frame, unsigned int size)
{

    if(size < FRAME_SIZE)
    {
        return false;
    }

    return (_CalcChecksum(frame, FRAME_SIZE) == 0)? true : false;
}

int Load_GetInfo(Load_Info_t *info, Load_SensorRaw_t *raw)
{
    int32_t weight;
    uint8_t status;
    uint8_t buf[sizeof(weight)];
    unsigned int i;
    int ret = 0;
    union
    {
        int32_t i32;
        uint8_t u8[4];
    }un32;

    const Master_Rx_t rx =
    {
            .serial = _SERIAL,
            .head = FRAME_HEAD,
            .size = FRAME_SIZE,
            .timeout = 1000,
            .check = _FrameCheck
    };

    HW_Config(HW_Out_LoadEn, HW_State_Active);
    HAL_Delay(50);
    Master_StartRx(&rx);
    while(Master_State() == Master_State_Rxing)
    {
        IDLE();
    }

    if(! Active_IsSetted(Active_User))
    {
    	HW_Config(HW_Out_LoadEn, HW_State_Inactive);
    }

    do
    {
        if(Master_State() != Master_State_FrameIn)
        {
            info->statusBits = STATUS_ERROR;
            info->weight = 0;
            ret = -1;
            break;
        }

#if 0
        uint8_t rbuf[FRAME_SIZE];

        unsigned int size = Master_RxSize();
        Master_RxBufferRead(0, rbuf, size);
        printf("Load: RX: ");
        for(i = 0; i < size; i++)
        {
            printf("%02x ", (unsigned)rbuf[i]);
        }
        printf("\n");
#endif

        Master_SetRxBufferOffset(1);
        Master_RxBufferTake(&status, sizeof(status));
        info->statusBits = status;
        if(status > STATUS_NOT_CALIBRATED)
        {
            info->weight = 0;
            ret = -2;
            break;
        }

        Master_RxBufferTake(buf, sizeof(buf));
        // 按小端顺序存储
        un32.u8[0] = buf[3];
        un32.u8[1] = buf[2];
        un32.u8[2] = buf[1];
        un32.u8[3] = buf[0];
        weight = un32.i32;
        info->weight = (float)weight / 1000.0;
    }while(0);

    if(raw != NULL)
    {
        unsigned int j;
        uint8_t rawBuf[sizeof(int32_t) * LOAD_SENSOR_NUM];
        Master_RxBufferRead(FRAME_RAW_DATA_OFFSET, rawBuf, sizeof(rawBuf));

        j = 0;
        for(i = 0; i < LOAD_SENSOR_NUM; i++)
        {
            // 按小端顺序存储
            un32.u8[0] = rawBuf[j + 3];
            un32.u8[1] = rawBuf[j + 2];
            un32.u8[2] = rawBuf[j + 1];
            un32.u8[3] = rawBuf[j];
            raw->adcs[i] = un32.i32;
            j += 4;
        }
    }

    return ret;
}

int Load_ShellCmd(Stream_t *stream, int argc, char *argv[])
{
    int ret, i;
    Load_Info_t info;
    Load_SensorRaw_t raw;

    chprintf(stream, "Getting load info ...\n");
    ret = Load_GetInfo(&info, &raw);
    chprintf(stream, "Load: result = %d, status = 0x%02x, weight = %.3fKg\n",
            ret, info.statusBits, info.weight);
    if(ret != -1)
    {
        for(i = 0; i < LOAD_SENSOR_NUM; i++)
        {
            chprintf(stream, "Sensor%d: %ld\n", i + 1, raw.adcs[i]);
        }
    }

    return 0;
}
